﻿using System.IO;
using System.Text;
using System.Collections.Generic;

namespace SolutionGeneratorHelper
{
    internal class Field
    {
        private string m_attr;
        private string m_value;
        public string Attr { get => m_attr; set => m_attr = value; }
        public string Value { get => m_value; set => m_value = value; }

        public Field(string _attr, string _value)
        {
            Attr = _attr;
            Value = _value;
        }
    }

    internal abstract class Node : ISerializable
    {
        private Node m_parent;
        private List<Node> m_children;
        private List<Field> m_properties;
        private string m_name;
        private Field m_content;

        internal string Name { get => m_name; set => m_name = value; }
        internal Field Content { get => m_content; set => m_content = value; }
        internal Node Parent { get => m_parent; set => m_parent = value; }
        internal List<Node> Children { get => m_children; set => m_children = value; }
        internal List<Field> Properties { get => m_properties; set => m_properties = value; }

        internal Node() { Init(); }
        internal Node(Field _content) { Content = _content; Init(); }

        protected virtual void Init()
        {
            Properties = new List<Field>();
            Children = new List<Node>();
        }


        protected virtual void SetField(ref Field _ref, Field _value)
        {
            Field f = null;
            if (null != _ref)
                f = GetField(_ref.Attr);
            
            if (null == f)
            {
                f = _value;
                Properties.Add(f);
            }
            else
            {
                f.Attr = _value.Attr;
                f.Value = _value.Value;
            }
            _ref = f;
        }

        protected virtual Field GetField(string _attr)
        {
            foreach(Field f in Properties)
            {
                if (_attr == f.Attr)
                    return f;
            }
            return null;
        }

        public abstract string Serialize();
        public abstract void Serialize(StringBuilder _sb);
    }

    internal class CommonNode : Node, INode
    {
        public CommonNode() { }
        public CommonNode(Field _content) : base(_content) { }

        public virtual void InsertChild(Node _node)
        {
            _node.Parent = this;
            Children.Add(_node);
        }

        public virtual void RemoveChild(Node _node)
        {
            Children.Remove(_node);
            _node.Parent = null;
        }

        public virtual void RemoveChildren()
        {
            Children.Clear();
        }

        public virtual void RemoveFromParent()
        {
            Children.Clear();
            Parent.Children.Remove(this);
            Parent = null;
        }

        public override string Serialize()
        {
            StringBuilder sb = new StringBuilder(1024);
            var str = new Utf8StringWriter(sb);
            Serialize(sb);
            return str.ToString();
        }

        public override void Serialize(StringBuilder _sb)
        {
            foreach (Node n in Children)
            {
                n.Serialize(_sb);
            }
        }
    }


    internal class Utf8StringWriter : StringWriter
    {
        public Utf8StringWriter() : base() { }
        public Utf8StringWriter(StringBuilder _sb) : base(_sb) { }

        public override Encoding Encoding
        {
            get { return Encoding.UTF8; }
        }
    }
}

